package com.aleyn.router.executor

import android.util.Log
import com.aleyn.router.util.wLog
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.CancellationException
import java.util.concurrent.ExecutionException
import java.util.concurrent.Future
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import kotlin.math.max
import kotlin.math.min

/**
 * @author: Aleyn
 * @date: 2023/6/9 16:58
 *
 * LRouter 框架默认的线程池执行器。
 * 这是一个自定义的 [ThreadPoolExecutor]，用于执行后台任务，如路由和拦截器的初始化。
 */

// 获取 CPU 核心数
internal val CPU_COUNT = Runtime.getRuntime().availableProcessors()

// 计算核心线程数，最小为 3，最大为 6，且不超过 CPU 核心数 - 1
internal val CORE_POOL_SIZE = max(3, min(CPU_COUNT - 1, 6))

// 非核心线程的闲置超时时间，单位秒
internal const val KEEP_ALIVE_SECONDS = 30L

/**
 * 默认的线程池实现。
 * 核心线程数和最大线程数均为 [CORE_POOL_SIZE]。
 * 使用 [ArrayBlockingQueue] 作为任务队列，容量为 64。
 * 使用 [DefaultThreadFactory] 创建线程。
 */
internal class DefaultPoolExecutor : ThreadPoolExecutor(
    CORE_POOL_SIZE,
    CORE_POOL_SIZE, KEEP_ALIVE_SECONDS,
    TimeUnit.SECONDS,
    ArrayBlockingQueue(64),
    DefaultThreadFactory()
) {

    /**
     * 任务执行后的回调方法。
     * 用于捕获并记录在任务执行过程中未被捕获的异常。
     */
    override fun afterExecute(r: Runnable?, throwable: Throwable?) {
        super.afterExecute(r, throwable)
        var t = throwable
        // 如果任务本身没有抛出异常，但它是一个 Future，则尝试获取其结果以检查异常
        if (t == null && r is Future<*>) {
            try {
                (r as Future<*>).get()
            } catch (ce: CancellationException) {
                t = ce
            } catch (ee: ExecutionException) {
                t = ee.cause
            } catch (ie: InterruptedException) {
                Thread.currentThread().interrupt()
            }
        }
        // 如果检测到异常，则打印警告日志
        if (t != null) {
            """
            Running task appeared exception! Thread [${Thread.currentThread().name}], because [${t.message}]
            ${Log.getStackTraceString(t)}
            """.trimIndent().wLog()
        }
    }

}